#region Copyright (c) 2006-2010 Acme LLC, All Rights Reserved
//--------------------------------------------------------------------- *
//                          Acme  LLC                           *
//             Copyright (c) 2006-2010 All Rights reserved              *
//                                                                      *
//                                                                      *
//This file and its contents are protected by United States and         *
//International copyright laws.  Unauthorized reproduction and/or       *
//distribution of all or any portion of the code contained herein       *
//is strictly prohibited and will result in severe civil and criminal   *
//penalties.  Any violations of this copyright will be prosecuted       *
//to the fullest extent possible under law.                             *
//                                                                      *
//THE SOURCE CODE CONTAINED HEREIN AND IN RELATED FILES IS PROVIDED     *
//TO THE REGISTERED DEVELOPER FOR THE PURPOSES OF EDUCATION AND         *
//TROUBLESHOOTING. UNDER NO CIRCUMSTANCES MAY ANY PORTION OF THE SOURCE *
//CODE BE DISTRIBUTED, DISCLOSED OR OTHERWISE MADE AVAILABLE TO ANY     *
//THIRD PARTY WITHOUT THE EXPRESS WRITTEN CONSENT OF WIDGETSPHERE LLC   *
//                                                                      *
//UNDER NO CIRCUMSTANCES MAY THE SOURCE CODE BE USED IN WHOLE OR IN     *
//PART, AS THE BASIS FOR CREATING A PRODUCT THAT PROVIDES THE SAME, OR  *
//SUBSTANTIALLY THE SAME, FUNCTIONALITY AS ANY WIDGETSPHERE PRODUCT.    *
//                                                                      *
//THE REGISTERED DEVELOPER ACKNOWLEDGES THAT THIS SOURCE CODE           *
//CONTAINS VALUABLE AND PROPRIETARY TRADE SECRETS OF WIDGETSPHERE,      *
//INC.  THE REGISTERED DEVELOPER AGREES TO EXPEND EVERY EFFORT TO       *
//INSURE ITS CONFIDENTIALITY.                                           *
//                                                                      *
//THE END USER LICENSE AGREEMENT (EULA) ACCOMPANYING THE PRODUCT        *
//PERMITS THE REGISTERED DEVELOPER TO REDISTRIBUTE THE PRODUCT IN       *
//EXECUTABLE FORM ONLY IN SUPPORT OF APPLICATIONS WRITTEN USING         *
//THE PRODUCT.  IT DOES NOT PROVIDE ANY RIGHTS REGARDING THE            *
//SOURCE CODE CONTAINED HEREIN.                                         *
//                                                                      *
//THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE.              *
//--------------------------------------------------------------------- *
#endregion
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Windows.Forms;
using System.Text.RegularExpressions;

namespace Acme.AuditExample.Install
{
	[RunInstaller(true)]
	public partial class DatabaseInstaller : Installer
	{
		public const string EXENAME_KEY = "-EXENAME";
		public const string DLLNAME_KEY = "-DLLNAME";
		public const string DEFAULT_APPDB_KEY = "-APPDB";
		public const string DEFAULT_MASTERDB_KEY = "-MASTERDB";

		public string[] PARAMKEYS_UPGRADE = new string[] { "upgrade", "u" };
		public string[] PARAMKEYS_MASTERDB = new string[] { "master", "masterdb", "m", "create", "c", DEFAULT_MASTERDB_KEY };
		public string[] PARAMKEYS_HELP = new string[] { "help", "h", "?" };
		public string[] PARAMKEYS_APPDB = new string[] { "applicationdb", "application", "a", "app", "appdb", DEFAULT_APPDB_KEY };



		private string _connectionString = string.Empty;
		private bool _newInstall = false;

		public DatabaseInstaller()
		{
			InitializeComponent();
		}

		public override void Install(System.Collections.IDictionary stateSaver)
		{
			base.Install(stateSaver);

			Dictionary<string, string> commandParams = GetCommandLineParameters();
			if (PrintHelp(commandParams))
				return;

			string appDbConnectionString = GetAppDbString(commandParams);
			string masterDbConnectionString = GetMasterDbConnectionString(commandParams);
			bool upgrade = string.IsNullOrEmpty(masterDbConnectionString);
			upgrade = GetUpgradeDbSetting(commandParams, upgrade);

			if ((upgrade && !string.IsNullOrEmpty(appDbConnectionString)) || (!upgrade && !string.IsNullOrEmpty(appDbConnectionString) && !string.IsNullOrEmpty(masterDbConnectionString)))
			{
				_newInstall = !upgrade;
				CommandLineInstall(masterDbConnectionString, appDbConnectionString);
			}
			else
			{
				UIInstall();
			}

		}

		private string GetDbName(string newDatabaseConnectionString)
		{
			if (!string.IsNullOrEmpty(newDatabaseConnectionString))
			{
				Regex regEx = new Regex(@"(Initial Catalog\s*=|Database\s*=)\s*([\w-]+)[;]?");
				Match firstMatch = regEx.Match(newDatabaseConnectionString);
				if (firstMatch != null && firstMatch.Groups != null && firstMatch.Groups.Count >= 3)
				{
					return firstMatch.Groups[2].Value;
				}
				else
				{
					throw new Exception("Could not find database name in connecton string : " + newDatabaseConnectionString);
				}
			}
			else
			{
				throw new Exception("Empty database connection string : " + newDatabaseConnectionString);
			}
		}

		private bool GetUpgradeDbSetting(Dictionary<string, string> commandParams, bool defaultValue)
		{
			bool retVal = defaultValue;
			foreach (string s in PARAMKEYS_UPGRADE)
			{
				if (commandParams.ContainsKey(s))
				{
					retVal = true;
					break;
				}
			}
			return retVal;
		}

		private string GetMasterDbConnectionString(Dictionary<string, string> commandParams)
		{
			string retVal = string.Empty;
			foreach (string s in PARAMKEYS_MASTERDB)
			{
				if (commandParams.ContainsKey(s))
				{
					retVal = commandParams[s];
					break;
				}
			}
			return retVal;
		}

		private string GetAppDbString(Dictionary<string, string> commandParams)
		{
			string retVal = string.Empty;
			foreach (string s in PARAMKEYS_APPDB)
			{
				if (commandParams.ContainsKey(s))
				{
					retVal = commandParams[s];
					break;
				}
			}
			return retVal;
		}

		private bool PrintHelp(Dictionary<string, string> commandParams)
		{
			bool retVal = false;
			foreach (string s in PARAMKEYS_HELP)
			{
				if (commandParams.ContainsKey(s))
				{
					retVal = true;
					Console.WriteLine("public string[] PARAMKEYS_UPGRADE = new string[] { \"-upgrade\", \"-u\" }");
					Console.WriteLine("public string[] PARAMKEYS_MASTERDB = new string[] { \"-master\", \"-masterdb\", \"-m\", \"-create\", \"-c\" };");
					Console.WriteLine("public string[] PARAMKEYS_HELP = new string[] { \"-help\", \"-h\", \"-?\" };");
					Console.WriteLine("public string[] PARAMKEYS_APPDB = new string[] { \"-applicationdb\", \"-application\", \"-a\", \"-app\", \"-appdb\" };");
					break;
				}
			}
			return retVal;
		}

		private Dictionary<string, string> GetCommandLineParameters()
		{
			Dictionary<string, string> retVal = new Dictionary<string, string>();
			string[] args = Environment.GetCommandLineArgs();

			int loopcount = 0;
			foreach (string arg in args)
			{
				Regex regEx = new Regex(@"-(\w+)(:(.*))?");
				Match regExMatch = regEx.Match(arg);
				if (regExMatch.Success)
				{
					retVal.Add(regExMatch.Groups[1].Value, regExMatch.Groups[3].Value);
				}
				else
				{
					string tmpKey = Guid.NewGuid().ToString();
					if (loopcount == 0)
						tmpKey = EXENAME_KEY;
					else if (loopcount == 1)
						tmpKey = DLLNAME_KEY;
					else if (loopcount == 2)
						tmpKey = DEFAULT_APPDB_KEY;
					else if (loopcount == 3)
						tmpKey = DEFAULT_MASTERDB_KEY;
					retVal.Add(tmpKey, arg);
				}
				loopcount++;
			}

			return retVal;
		}

		public void CommandLineInstall(string masterConnectionString, string newDatabaseConnectionString)
		{
			if (_newInstall)
			{
				string newDatabaseName = GetDbName(newDatabaseConnectionString);
				SqlServers.CreateDatabase(masterConnectionString, newDatabaseName);
				DateTime startTime = DateTime.Now;
				while (DateTime.Now.Subtract(startTime).TotalSeconds < 10)
				{
					Application.DoEvents();
				}
			}
			try
			{
				UpgradeInstaller.UpgradeDatabase(newDatabaseConnectionString, _newInstall);
			}
			catch (Exception ex)
			{
				System.Threading.Thread.Sleep(8000);
				try
				{
					UpgradeInstaller.UpgradeDatabase(newDatabaseConnectionString, _newInstall);
				}
				catch
				{
					throw;
				}
			}
		}

		public void UIInstall()
		{
			if (IdentifyDatabaseConnectionString())
				UpgradeInstaller.UpgradeDatabase(_connectionString, _newInstall);
		}

		public override void Uninstall(System.Collections.IDictionary savedState)
		{
			base.Uninstall(savedState);
		}

		public bool IdentifyDatabaseConnectionString()
		{
			IdentifyDatabaseForm idf = new IdentifyDatabaseForm();
			if (idf.ShowDialog() == DialogResult.OK)
			{
				_connectionString = idf.ConnectionString;
				_newInstall = idf.CreatedDatabase;
				return true;
			}
			return false;
		}


	}
}